#include <list>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include "drpc.h"
#include "drpc_netproto_def.h"
#include "netproto_srv.h"

//static std::list<int> g_lst_handles;

typedef int (*pmfhandle) (int);
typedef struct _srv_entry
{
  int cmd;
  pmfhandle handle;
} srv_entry;

static const srv_entry s_srv_entry[] =
{
  {DRPC_NP_CMD_BUILTINTYPE,     Drpc_srv__NetProtoAdd},
  {DRPC_NP_CMD_PASSSTRUCT,      Drpc_srv__NetProtoGetStu},
  {DRPC_NP_CMD_PASSSTRING,      Drpc_srv__NetProtoGetStr},
};

static
int dispatch(int handle, int cmd)
{
  int count = sizeof(s_srv_entry) / sizeof(srv_entry);
  for (int n = 0; n < count; ++n) {
    if (s_srv_entry[n].cmd == cmd) {
      int ret = s_srv_entry[n].handle(handle);
      return 0;
    }
  }
  printf("%s==> pmfhandle not found!\n", __FUNCTION__);
  return -1;
}

//int drpc_destroy_cli_handles()
//{
//  std::list<int> lst_handles;
//  {
//    lst_handles.swap(g_lst_handles);
//  }
//  //printf("%zu handles will be destroyed\n", lst_handles.size());
//  std::list<int>::iterator iter = lst_handles.begin();
//  for (; iter != lst_handles.end(); iter++) {
//    //shutdown(*iter, SHUT_RDWR);
//    close(*iter);
//  }
//  return 0;
//}

int drpc_netproto_srv_routine()
{
  int cli_handle = 0;
  int handle = drpc_call_core_init_srv();
  if (handle < 0) {
    printf("%s==> srv init error\n", __FUNCTION__);
    return -1;
  }
  while ((cli_handle = drpc_call_core_accept_srv(handle)) > 0) {
    //printf("%s==> client new conn sock=%d\n", __FUNCTION__, cli_handle);
    pkt_hdr_t hdr;
    int ret = drpc_call_core_fetch_head_srv(cli_handle, &hdr);
    if (ret < 0) {
      printf("%s==> **** read request error\n", __FUNCTION__);
      drpc_call_core_end_cli(cli_handle);
      continue;
    } else {
      //printf("%s==> cmd=%d cnt=%d len=%d\n", __FUNCTION__, hdr.cmd, hdr.cnt, hdr.len);
    }
    ret = dispatch(cli_handle, hdr.cmd );
    drpc_call_core_end_cli_srv(cli_handle);
    //if (ret < 0) {
    //  drpc_call_core_end_cli(cli_handle);
    //  continue;
    //} else {
    //  g_lst_handles.push_back(cli_handle);
    //}
  }
  drpc_call_core_end_srv(handle);
  return 0;
}


int Drpc_srv__NetProtoAdd(int handle)
{
  //printf("%s:%d\n", __FUNCTION__, __LINE__);
  // input param
  int a,b;
  // fetch param
  int ret = drpc_call_core_input_param_srv PARM2(handle, DRPC_NP_CMD_BUILTINTYPE, a, b);
  if (ret < 0) return -1;
  // call local method
  int ou_c = a + b;
  //printf("netproto_srv %d+%d=%d\r\n", a, b, ou_c);
  // notify result
  ret = drpc_call_core_output_param_srv PARM1(handle, DRPC_NP_CMD_BUILTINTYPE, ou_c);
  if (ret < 0) return -1;
  return 0;
}

int Drpc_srv__NetProtoGetStu(int handle)
{
  //printf("%s:%d\n", __FUNCTION__, __LINE__);
  // input param
  MyStu_t t;
  // fetch param
  int ret = drpc_call_core_input_param_srv PARM1(handle, DRPC_NP_CMD_PASSSTRUCT, t);
  if (ret < 0) return -1;
  //printf("netproto_srv recv struct:{%s,%d}\r\n", t.szName, t.nAge);
  // call local method
  strncpy(t.szName, "Jason", sizeof(t.szName)-1);
  t.nAge = 18;
  // notify result
  ret = drpc_call_core_output_param_srv PARM1(handle, DRPC_NP_CMD_PASSSTRUCT, t);
  if (ret < 0) return -1;
  return 0;
}

int Drpc_srv__NetProtoGetStr(int handle)
{
  //printf("%s:%d\n", __FUNCTION__, __LINE__);
  // input param
  MyStr_t s;
  // fetch param
  int ret = drpc_call_core_input_param_srv PARM1(handle, DRPC_NP_CMD_PASSSTRING, s);
  if (ret < 0) return -1;
  //printf("netproto_srv input param==>%s\r\n", s.szStr);
  strncpy(s.szStr, "message from srv", sizeof(s.szStr)-1);
  //printf("netproto_srv output param==>%s\r\n", s.szStr);
  // notify result
  ret = drpc_call_core_output_param_srv PARM1(handle, DRPC_NP_CMD_PASSSTRING, s);
  if (ret < 0) return -1;
  return 0;
}
